package au.com.handsunited.dao.hibernate;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.com.handsunited.dao.UserDAO;
import au.com.handsunited.model.BaseEntity;
import au.com.handsunited.model.User;

/**
 *
 * @author arunda
 * @date 19/12/2006 4:21:41 PM
 */
public class UserDAOHibernate extends EntityDAOHibernate implements UserDAO {

	private static Logger logger = LoggerFactory.getLogger(UserDAOHibernate.class);


	/**
	 *
	 */
	public UserDAOHibernate() {
		super();
	}


	/**
	 * @see au.com.handsunited.dao.impl.UserDAO#createUser(au.com.handsunited.model.User)
	 */
	@Override
	public User createUser(User user) {
		getHibernateTemplate().saveOrUpdate(user);

		if (logger.isDebugEnabled()) {
			logger.debug("user id set to: {}", user.getId());
		}
		return user;
	}


	/**
	 * @see au.com.handsunited.dao.impl.UserDAO#updateUser(au.com.handsunited.model.User)
	 */
	@Override
	public User updateUser(User user) {
		return (User) updateEntity(user);
	}


	/**
	 * @see au.com.handsunited.dao.impl.UserDAO#getUser(java.lang.Long)
	 */
	public User getUser(Long userId) {
		return (User) getEntity(userId, User.class);
	}

	/**
	 * @see au.com.handsunited.dao.impl.UserDAO#findUserByUsername(java.lang.String)
	 */
	public User findUserByUsername(String username) {

		List<User> l =
			getHibernateTemplate().findByNamedQuery("User.findByUsername", username);

//		index();

		if (l.isEmpty()) {
			return null;
		} else if (l.size() == 1) {
			User u = l.get(0);
			return u;
		} else {
			if (logger.isWarnEnabled()) {
				logger.warn("Multiple entries found for username[{}]", username);
			}
			return null;
		}
	}


	/**
	 * @see au.com.handsunited.dao.impl.UserDAO#getUsers()
	 */
	public List<User> getUsers() {
		return getHibernateTemplate().find("from User");
	}


	/**
	 * @see au.com.handsunited.dao.UserDAO#getUsersPaginated(int, int)
	 */
	@Override
	public List<User> getUsersPaginated(int firstResult, int maxResults) {

		Query query = getSession().createQuery("from User");
		query.setFirstResult(firstResult);
		query.setMaxResults(maxResults);
		List<User> users = query.list();
		return users;
	}


	/**
	 * @see au.com.handsunited.dao.UserDAO#searchActiveUsers(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public List<User> searchActiveUsers(String firstName, String lastName,
			String emailAddress) {

		Criteria userSearchCriteria = getSession().createCriteria(User.class);

		userSearchCriteria.add(Restrictions.eq("active", Boolean.TRUE));

		if (StringUtils.isNotBlank(firstName)) {
			userSearchCriteria.add(Restrictions.ilike("firstName", firstName, MatchMode.ANYWHERE));
		}

		if (StringUtils.isNotBlank(lastName)) {
			userSearchCriteria.add(Restrictions.ilike("lastName", lastName, MatchMode.ANYWHERE));
		}

		if (StringUtils.isNotBlank(emailAddress)) {
			userSearchCriteria.add(Restrictions.ilike("username", emailAddress, MatchMode.EXACT));
		}

		userSearchCriteria.addOrder(Order.asc("firstName"));
		userSearchCriteria.addOrder(Order.asc("lastName"));

		return userSearchCriteria.list();
	}


	private void index() {
		FullTextSession fullTextSession = Search.createFullTextSession(getSession());
		Transaction tx = fullTextSession.beginTransaction();
		List<User> users = getSession().createQuery("from User as users").list();
		for (User user : users) {
		    fullTextSession.index(user);
		}

		List<BaseEntity> entities = getSession().createQuery("from BaseEntity as entities").list();
		for(BaseEntity entity: entities) {
			fullTextSession.index(entity);
		}
	}
}
